﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SmartMathLibrary.SQLServer.Commands
{
    /// <summary>
    /// Provides methods to deal with the most kinds of factorials.
    /// </summary>
    [Serializable]
    internal static class Factorials
    {
        /// <summary>
        /// Calculates the factorial of the specified number.
        /// </summary>
        /// <param name="value">The specified number.</param>
        /// <returns>The factorial of the number.</returns>
        public static uint Factorial(uint value)
        {
            uint result = 1;

            for (uint i = value; i >= 1; i--)
            {
                result *= i;
            }

            return result;
        }

        /// <summary>
        /// Calculates the factorial of the specified number.
        /// </summary>
        /// <param name="value">The specified number.</param>
        /// <returns>The factorial of the number.</returns>
        public static UInt64 Factorial(UInt64 value)
        {
            UInt64 result = 1;

            for (UInt64 i = value; i >= 1; i--)
            {
                result *= i;
            }

            return result;
        }

        /// <summary>
        /// A list of factorials up to 10!.
        /// </summary>
        /// <returns>The list of factorials.</returns>
        public static UInt64[] FactorialList10()
        {
            UInt64[] list = new UInt64[11];

            list[0] = 1;
            list[1] = 1;
            list[2] = 2;
            list[3] = 6;
            list[4] = 24;
            list[5] = 120;
            list[6] = 720;
            list[7] = 5040;
            list[8] = 40320;
            list[9] = 362880;
            list[10] = 3628800;

            return list;
        }

        /// <summary>
        /// A list of factorials up to 20!.
        /// </summary>
        /// <returns>The list of factorials.</returns>
        public static UInt64[] FactorialList20()
        {
            UInt64[] list = new UInt64[21];

            list[0] = 1;
            list[1] = 1;
            list[2] = 2;
            list[3] = 6;
            list[4] = 24;
            list[5] = 120;
            list[6] = 720;
            list[7] = 5040;
            list[8] = 40320;
            list[9] = 362880;
            list[10] = 3628800;
            list[11] = 39916800;
            list[12] = 479001600;
            list[13] = 6227020800;
            list[14] = 87178291200;
            list[15] = 1307674368000;
            list[16] = 20922789888000;
            list[17] = 355687428096000;
            list[18] = 6402373705728000;
            list[19] = 121645100408832000;
            list[20] = 2432902008176640000;

            return list;
        }

        /// <summary>
        /// A list of factorials up to 65!.
        /// </summary>
        /// <returns>The list of factorials.</returns>
        public static UInt64[] FactorialList65()
        {
            UInt64[] list = new UInt64[66];

            list[0] = 1;
            list[1] = 1;
            list[2] = 2;
            list[3] = 6;
            list[4] = 24;
            list[5] = 120;
            list[6] = 720;
            list[7] = 5040;
            list[8] = 40320;
            list[9] = 362880;
            list[10] = 3628800;
            list[11] = 39916800;
            list[12] = 479001600;
            list[13] = 6227020800;
            list[14] = 87178291200;
            list[15] = 1307674368000;
            list[16] = 20922789888000;
            list[17] = 355687428096000;
            list[18] = 6402373705728000;
            list[19] = 121645100408832000;
            list[20] = 2432902008176640000;
            list[21] = 14197454024290336768;
            list[22] = 17196083355034583040;
            list[23] = 8128291617894825984;
            list[24] = 10611558092380307456;
            list[25] = 7034535277573963776;
            list[26] = 16877220553537093632;
            list[27] = 12963097176472289280;
            list[28] = 12478583540742619136;
            list[29] = 11390785281054474240;
            list[30] = 9682165104862298112;
            list[31] = 4999213071378415616;
            list[32] = 12400865694432886784;
            list[33] = 3400198294675128320;
            list[34] = 4926277576697053184;
            list[35] = 6399018521010896896;
            list[36] = 9003737871877668864;
            list[37] = 1096907932701818880;
            list[38] = 4789013295250014208;
            list[39] = 2304077777655037952;
            list[40] = 18376134811363311616;
            list[41] = 15551764317513711616;
            list[42] = 7538058755741581312;
            list[43] = 10541877243825618944;
            list[44] = 2673996885588443136;
            list[45] = 9649395409222631424;
            list[46] = 1150331055211806720;
            list[47] = 17172071447535812608;
            list[48] = 12602690238498734080;
            list[49] = 8789267254022766592;
            list[50] = 15188249005818642432;
            list[51] = 18284192274659147776;
            list[52] = 9994050523088551936;
            list[53] = 13175843659825807360;
            list[54] = 10519282829630636032;
            list[55] = 6711489344688881664;
            list[56] = 6908521828386340864;
            list[57] = 6404118670120845312;
            list[58] = 2504001392817995776;
            list[59] = 162129586585337856;
            list[60] = 9727775195120271360;
            list[61] = 3098476543630901248;
            list[62] = 7638104968020361216;
            list[63] = 1585267068834414592;
            list[64] = 9223372036854775808;
            list[65] = 9223372036854775808;

            return list;
        }
    }
}